<?php
/**
 * Config
 * 
 * 作者:  姚刚 (yaogang@the9sense.com)
 * 创建时间: 2011-02-24 00:14:35
 * 修改记录: 
 * 
 * $Id: Config.php 2 2011-03-08 01:31:19Z coosuu@gmail.com $
 */

class Config {

    private $_values = array();

    private static $_loaded = array();

    private static $_instance = null;

    public static function &getInstance() {

        if (!self::$_instance) {
            self::$_instance = new self;
        }
        return self::$_instance;
    }

    public function set($key, $value) {

        $this->_values[$key] = $value;
    }

    public function get($key, $defaultValue = null) {

        $config =& Config::getInstance();
        $value = $config->load($key);
        if ($value !== null) {
            return $value;
        }

        return $defaultValue;
    }

    protected function load($key) {

        if ($this->exists($key)) {
            return $this->_values[$key];
        }

        $configFileName = $this->getConfigFileName($key);
        if (!$configFileName) {
            return null;
            //throw new Config_Exception('Config::get ' . $key . ' error, Cannot found Config file');
        }

        // 如果文件已经加载过，直接匹配
        if (in_array($configFileName, self::$_loaded)) {
            return $this->match($key);
        }

        require_once $configFileName;
        self::$_loaded[] = $configFileName;

        $rootKey = $this->getRootKey();

        // 将文件中的值都设置到内存中
        $this->set($rootKey, $conf);

        return $this->match($key);
    }

    protected function exists($key) {

        return array_key_exists($key, $this->_values);
    }

    protected function getConfigFileName($key) {

        $this->_rootKey = '';

        $appConfigPath = APP_PATH . '/config/';
        $platConfigPath = '';
        if (defined('PLATFORM') && trim(PLATFORM)) {
            $platConfigPath = $appConfigPath . ucwords(strtolower(trim(PLATFORM))) . '/';
        }

        $tmp = explode('.', $key);
        $depth = count($tmp);

        // 检查平台目录有无配置文件
        if ($platConfigPath) {
            for ($i = $depth; $i > 0; $i--) {
                $configFile = $platConfigPath;
                $configFile .= implode('/', array_slice($tmp, 0, $i)) . '.php';
                if (file_exists($configFile)) {
                    $this->_rootKey = implode('.', array_slice($tmp, 0, $i));
                    return $configFile;
                }
            }
        }

        // 接着检查平台目录的global.php文件
        $configFile = $platConfigPath . 'global.php';
        if (file_exists($configFile)) {
            return $configFile;
        }

        // 平台目录没有就去APP配置目录找
        for ($i = $depth; $i > 0; $i--) {
            $configFile = $appConfigPath;
            $configFile .= implode('/', array_slice($tmp, 0, $i)) . '.php';
            if (file_exists($configFile)) {
                $this->_rootKey = implode('.', array_slice($tmp, 0, $i));
                return $configFile;
            }
        }

        // 检查APP配置目录中的global.php
        $configFile = $appConfigPath . 'global.php';
        if (file_exists($configFile)) {
            return $configFile;
        }

        return null;
    }

    protected function getRootKey() {

        return $this->_rootKey;
    }

    protected function match($key) {

        if ($this->exists($key)) {
            return $this->_values[$key];
        }

        // 文件名作为节点
        $leafKey = $this->getRootKey();

        $tmpValue = $this->_values[$leafKey];
        $leftKeyParts = explode('.', substr($key, strlen($leafKey)+1));
        $leftDepth = count($leftKeyParts);

        // 用key中的剩余部分去遍历配置文件
        $matchDepth = 0;
        foreach ($leftKeyParts as $key) {
            $value = $tmpValue;
            if (!$value) {
                continue;
            }
            if (array_key_exists($key, $value)) {
                $matchDepth++;
                $tmpValue = $value[$key];
            }
        }

        // 如果剩余key的深度和遍历的深度一样，则说明找到配置值
        if ($matchDepth == $leftDepth) {
            return $tmpValue;
        }

        return null;
    }
}
